﻿//   █
// ███

/**
 * 方块3的构造方法。
 * @return 方块3
 */
function Block3() {
    // 创建方块
    const block = new Block()

    // 初始化数据
    block.mBlocks[1][1].mUsed = block.mBlocks[2][0].mUsed = block.mBlocks[2][1].mUsed = block.mBlocks[2][2].mUsed = true

    // 初始化函数
    block.erase = Block3_Erase
    block.getBottom = Block3_GetBottom
    block.getTop = Block3_GetTop
    block.handleCannotMoveDown = Block3_HandleCannotMoveDown
    block.moveDown = Block3_MoveDown
    block.moveLeft = Block3_MoveLeft
    block.moveRight = Block3_MoveRight
    block.transform = Block3_Transform

    return block
}

/**
 * 擦除。
 * @param block 方块3
 */
function Block3_Erase(block) {
    var x, y, width, height

    switch (block.mShape) {
        case Shape.ONE:
            x = Const.GRID_SIZE * (block.mLine + 1)
            y = Const.GRID_SIZE * (block.mRow + 1)
            width = Const.GRID_SIZE
            height = Const.GRID_SIZE
            block.eraseRect(block, x, y, width, height)
            x = Const.GRID_SIZE * block.mLine
            y = Const.GRID_SIZE * (block.mRow + 2)
            width = Const.GRID_SIZE * 3
            height = Const.GRID_SIZE
            block.eraseRect(block, x, y, width, height)
            break
        case Shape.TWO:
            x = Const.GRID_SIZE * (block.mLine + 1)
            y = Const.GRID_SIZE * (block.mRow + 1)
            width = Const.GRID_SIZE
            height = Const.GRID_SIZE * 3
            block.eraseRect(block, x, y, width, height)
            x = Const.GRID_SIZE * (block.mLine + 2)
            y = Const.GRID_SIZE * (block.mRow + 2)
            width = Const.GRID_SIZE
            height = Const.GRID_SIZE
            block.eraseRect(block, x, y, width, height)
            break
        case Shape.THREE:
            x = Const.GRID_SIZE * block.mLine
            y = Const.GRID_SIZE * (block.mRow + 2)
            width = Const.GRID_SIZE * 3
            height = Const.GRID_SIZE
            block.eraseRect(block, x, y, width, height)
            x = Const.GRID_SIZE * (block.mLine + 1)
            y = Const.GRID_SIZE * (block.mRow + 3)
            width = Const.GRID_SIZE
            height = Const.GRID_SIZE
            block.eraseRect(block, x, y, width, height)
        case Shape.FOUR:
            x = Const.GRID_SIZE * block.mLine
            y = Const.GRID_SIZE * (block.mRow + 2)
            width = Const.GRID_SIZE
            height = Const.GRID_SIZE
            block.eraseRect(block, x, y, width, height)
            x = Const.GRID_SIZE * (block.mLine + 1)
            y = Const.GRID_SIZE * (block.mRow + 1)
            width = Const.GRID_SIZE
            height = Const.GRID_SIZE * 3
            block.eraseRect(block, x, y, width, height)
            break
    }
}

/**
 * 获取底端所在的行数。底端是指方块最下方的有效格。
 * @param block 方块3
 * @return 底端所在的行数
 */
function Block3_GetBottom(block) {
    if (block.mShape == Shape.ONE) {
        return block.mRow + 2
    }
    return block.mRow + 3
}

/**
 * 获取顶端所在的行数。顶端是指方块最上方的有效格。
 * @param block 方块3
 * @return 顶端所在的行数
 */
function Block3_GetTop(block) {
    if (block.mShape == Shape.THREE) {
        return block.mRow + 2
    }
    return block.mRow + 1
}

/**
 * 对不能下落的处理。
 * @param block 方块3
 */
function Block3_HandleCannotMoveDown(block) {
    switch (block.mShape) {
        case Shape.ONE:
            gExistentBlocks[block.mRow + 1][block.mLine + 1].mUsed = true
            gExistentBlocks[block.mRow + 1][block.mLine + 1].mColor = block.mColor
            for (var j = 0; j <= 2; j++) {
                gExistentBlocks[block.mRow + 2][block.mLine + j].mUsed = true
                gExistentBlocks[block.mRow + 2][block.mLine + j].mColor = block.mColor
            }
            break 
        case Shape.TWO:
            gExistentBlocks[block.mRow + 2][block.mLine + 2].mUsed = true
            gExistentBlocks[block.mRow + 2][block.mLine + 2].mColor = block.mColor
            for (var i = 1; i <= 3; i++) {
                gExistentBlocks[block.mRow + i][block.mLine + 1].mUsed = true
                gExistentBlocks[block.mRow + i][block.mLine + 1].mColor = block.mColor
            }
            break 
        case Shape.THREE:
            gExistentBlocks[block.mRow + 3][block.mLine + 1].mUsed = true
            gExistentBlocks[block.mRow + 3][block.mLine + 1].mColor = block.mColor
            for (var j = 0; j <= 2; j++) {
                gExistentBlocks[block.mRow + 2][block.mLine + j].mUsed = true
                gExistentBlocks[block.mRow + 2][block.mLine + j].mColor = block.mColor
            }
            break 
        case Shape.FOUR:
            gExistentBlocks[block.mRow + 2][block.mLine].mUsed = true
            gExistentBlocks[block.mRow + 2][block.mLine].mColor = block.mColor
            for (var i = 1; i <= 3; i++) {
                gExistentBlocks[block.mRow + i][block.mLine + 1].mUsed = true
                gExistentBlocks[block.mRow + i][block.mLine + 1].mColor = block.mColor
            }
            break 
    }
}

/**
 * 下落。
 * @param block 方块3
 * @return 成功则返回 true，否则返回 false
 */
function Block3_MoveDown(block) {
    switch (block.mShape) {
        case Shape.ONE:
            if (block.mRow == 17) {
                block.handleCannotMoveDown(block)
                return false
            }
            if (gExistentBlocks[block.mRow + 3][block.mLine].mUsed || 
                gExistentBlocks[block.mRow + 3][block.mLine + 1].mUsed || 
                gExistentBlocks[block.mRow + 3][block.mLine + 2].mUsed) {
                block.handleCannotMoveDown(block)
                return false
            }
            break 
        case Shape.TWO:
            if (block.mRow == 16) {
                block.handleCannotMoveDown(block)
                return false
            }
            if (gExistentBlocks[block.mRow + 4][block.mLine + 1].mUsed || 
                gExistentBlocks[block.mRow + 3][block.mLine + 2].mUsed) {
                block.handleCannotMoveDown(block)
                return false
            }
            break 
        case Shape.THREE:
            if (block.mRow == 16) {
                block.handleCannotMoveDown(block)
                return false
            }
            if (gExistentBlocks[block.mRow + 3][block.mLine].mUsed || 
                gExistentBlocks[block.mRow + 4][block.mLine + 1].mUsed || 
                gExistentBlocks[block.mRow + 3][block.mLine + 2].mUsed) {
                block.handleCannotMoveDown(block)
                return false
            }
            break
        case Shape.FOUR:
            if (block.mRow == 16) {
                block.handleCannotMoveDown(block)
                return false
            }
            if (gExistentBlocks[block.mRow + 3][block.mLine].mUsed || 
                gExistentBlocks[block.mRow + 4][block.mLine + 1].mUsed) {
                block.handleCannotMoveDown(block)
                return false
            }
            break
    }

    return Block_MoveDown(block)
}

/**
 * 左移。
 * @param block 方块3
 */
function Block3_MoveLeft(block) {
    switch (block.mShape) {
        case Shape.ONE:
            if (block.mLine == 0) {
                return
            }
            if (gExistentBlocks[block.mRow + 1][block.mLine].mUsed ||
                gExistentBlocks[block.mRow + 2][block.mLine - 1].mUsed) {
                return
            }
            break
        case Shape.TWO:
            if (block.mLine == -1) {
                return
            }
            if (gExistentBlocks[block.mRow + 1][block.mLine].mUsed ||
                gExistentBlocks[block.mRow + 2][block.mLine].mUsed ||
                gExistentBlocks[block.mRow + 3][block.mLine].mUsed) {
                return
            }
            break
        case Shape.THREE:
            if (block.mLine == 0) {
                return
            }
            if (gExistentBlocks[block.mRow + 2][block.mLine - 1].mUsed ||
                gExistentBlocks[block.mRow + 3][block.mLine].mUsed) {
                return
            }
            break
        case Shape.FOUR:
            if (block.mLine == 0) {
                return
            }
            if (gExistentBlocks[block.mRow + 1][block.mLine].mUsed ||
                gExistentBlocks[block.mRow + 2][block.mLine - 1].mUsed ||
                gExistentBlocks[block.mRow + 3][block.mLine].mUsed) {
                return
            }
            break
    }

    Block_MoveLeft(block)
}

/**
 * 右移。
 * @param block 方块3
 */
function Block3_MoveRight(block) {
    switch (block.mShape) {
        case Shape.ONE:
            if (block.mLine == 7) {
                return
            }
            if (gExistentBlocks[block.mRow + 1][block.mLine + 2].mUsed ||
                gExistentBlocks[block.mRow + 2][block.mLine + 3].mUsed) {
                return
            }
            break
        case Shape.TWO:
            if (block.mLine == 7) {
                return
            }
            if (gExistentBlocks[block.mRow + 1][block.mLine + 2].mUsed ||
                gExistentBlocks[block.mRow + 2][block.mLine + 3].mUsed ||
                gExistentBlocks[block.mRow + 3][block.mLine + 2].mUsed) {
                return
            }
            break
        case Shape.THREE:
            if (block.mLine == 7) {
                return
            }
            if (gExistentBlocks[block.mRow + 2][block.mLine + 3].mUsed ||
                gExistentBlocks[block.mRow + 3][block.mLine + 2].mUsed) {
                return
            }
            break
        case Shape.FOUR:
            if (block.mLine == 8) {
                return
            }
            if (gExistentBlocks[block.mRow + 1][block.mLine + 2].mUsed ||
                gExistentBlocks[block.mRow + 2][block.mLine + 2].mUsed ||
                gExistentBlocks[block.mRow + 3][block.mLine + 2].mUsed) {
                return
            }
            break
    }

    Block_MoveRight(block)
}

/**
 * 变形。
 * @param block 方块3
 */
function Block3_Transform(block) {
    switch (block.mShape) {
        case Shape.ONE:
            if (block.mRow == 17) {
                return
            }
            if (gExistentBlocks[block.mRow + 3][block.mLine + 1].mUsed) {
                return
            }
            block.erase(block)
            block.mBlocks[2][0].mUsed = false
            block.mBlocks[3][1].mUsed = true
            block.mShape = Shape.TWO
            break
        case Shape.TWO:
            if (block.mLine == -1) {
                return
            }
            if (gExistentBlocks[block.mRow + 2][block.mLine].mUsed) {
                return
            }
            block.erase(block)
            block.mBlocks[1][1].mUsed = false
            block.mBlocks[2][0].mUsed = true
            block.mShape = Shape.THREE
            break
        case Shape.THREE:
            if (block.mRow == 16) {
                return
            }
            if (gExistentBlocks[block.mRow + 1][block.mLine + 1].mUsed) {
                return
            }
            block.erase(block)
            block.mBlocks[2][2].mUsed = false
            block.mBlocks[1][1].mUsed = true
            block.mShape = Shape.FOUR
            break
        case Shape.FOUR:
            if (block.mLine == 8) {
                return
            }
            if (gExistentBlocks[block.mRow + 2][block.mLine + 2].mUsed) {
                return
            }
            block.erase(block)
            block.mBlocks[3][1].mUsed = false
            block.mBlocks[2][2].mUsed = true
            block.mShape = Shape.ONE
            break
    }

    block.draw(block)
}
